#include "grid.hpp"

grid::grid(size_type w_in, size_type h_in, grid::data_type fill)
    : base_type(w_in,h_in,fill)
{
    //empty
}

void load(grid & g, const std::string & path, bool textorbinary)
{
    std::ifstream in;

    if(textorbinary == grid::text)
    {
        in.open(path.c_str());
        if(!in)
            throw std::string("Could not open " + path + " to load grid.");
        grid::size_type x,y;
        grid::data_type z;
        while(in >> x >> y >> z)
        {
            if(x < g.width() && y < g.height()) g(x,y) = z;
        }
    }
    else if(textorbinary == grid::binary)
    {
        in.open(path.c_str(), std::ios::binary);
        if(!in)
            throw std::string("Could not open " + path + " to load grid.");
        //[four bytes of sizeof data][two bytes sizeof coordinate designation][two bytes n in n-tuple]
        //[a1][a1][a3]...[an][data_a]
        //[b1][b2].......[bn][data_b]
        //etc....

        //assert( sizeof(unsigned int) == 4 );
        //assert( sizeof(unsigned short) == 2 );

        unsigned int sizeofdatatype;
        unsigned short sizeofcoordcomponent;
        unsigned short npertuple;
        std::ifstream fin(path.c_str(),std::ios::binary);

        fin.read( (char*)(&sizeofdatatype), sizeof(unsigned int) );
        fin.read( (char*)(&sizeofcoordcomponent), sizeof(unsigned short) );
        fin.read( (char*)(&npertuple), sizeof(unsigned short) );

        std::ofstream fout( (path+"text").c_str() );
        unsigned short x;
        unsigned short y;
        grid::data_type data;
        fout << std::scientific << std::setprecision( std::numeric_limits<grid::data_type>::digits10 );
        while(fin)
        {
            fin.read( (char*)(&x), sizeofcoordcomponent );
            fin.read( (char*)(&y), sizeofcoordcomponent );
            fin.read( (char*)(&data), sizeofdatatype);
            fout << x << '\t' << y << '\t' << data << '\n';
        }
    }
    else
    { /* WTF!!? */ }
}

void write_file(grid & g, const std::string & path, bool textorbinary, grid::region & reg)
{
    if(textorbinary == grid::text)
    {
        std::ofstream fout(path.c_str());
        functions::to_stream strmf(fout);
        g.iterate_region(reg, strmf);
    }
    else if(textorbinary == grid::binary)
    {
        try
        {
            functions::to_binary tobin(path);
            g.iterate_region(reg, tobin);
        }
        catch(const std::string & s)
        {
            output << "write_file(binary, ...) caught exception:\n" << s
                      << "\nAttempting to save as text..." << std::endl;
            write_file(g, path, grid::text, reg);
            return;
        }
    }
    else
    { /*WTF!!!!!????*/ }
}

grid & operator *= (grid & a, const grid::data_type & c)
{
	for(grid::size_type i = 0; i < a.width(); ++i)
	{
		for(grid::size_type j = 0; j < a.height(); ++j)
			a(i,j) *= c;
	}
	return a;
}

//unsigned long thing_to_count(grid::boundary::const_reference ref) { return ref.second.size(); }
//note: inlined; see grid.h
//unsigned long thing_to_count(grid::region::const_reference ref) { return ref.dy; }
